﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace CollBrowser
{
    using mshtml;
    public partial class Form1 : DevComponents.DotNetBar.Office2007Form
    {



        /// <summary>
        /// 采集对像单个实例
        /// </summary>
        internal CollectionRecord record = new CollectionRecord();


        /// <summary>
        /// 当前操作的状态
        /// </summary>
        internal 当前操作功能项状态 State = 当前操作功能项状态.选取目录列表;
        Timer timer = new Timer();
        /// <summary>
        /// 引发 click 事件的记数 最小值为第一个引发的事件
        /// </summary>
        private int TagIndex = 0;
        /// <summary>
        /// 当前创建采集浏览器对像的索引
        /// </summary>
        private int workIndex = 0;
        private bool pause = false;

        public Form1()
        {
            InitializeComponent();
            Load += new EventHandler(Form1_Load);
            timer.Tick += new EventHandler(timer_Tick);

        }

        /// <summary>
        /// 节点集合
        /// </summary>
        private IDictionary<HtmlElement, NodeEntity> NodeDictionary = new Dictionary<HtmlElement, NodeEntity>();

        void Form1_Load(object sender, EventArgs e)
        {
            Load -= new EventHandler(Form1_Load);

            webBrowser1.ScriptErrorsSuppressed = false;

            webBrowser1.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(webBrowser1_DocumentCompleted);
            webBrowser1.Navigated += new WebBrowserNavigatedEventHandler(webBrowser1_Navigated);
        }

        void webBrowser1_Navigated(object sender, WebBrowserNavigatedEventArgs e)
        {
            new System.Threading.Thread(new System.Threading.ParameterizedThreadStart((o) =>
            {
                System.Threading.Thread.Sleep(1000);
                BeginInvoke(new Action(delegate
                {
                    buttonSelect.Enabled = true;
                }));
            })).Start(); ;
        }

        void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
        {

            //清空树节点
            treeView1.Nodes.Clear();
            TreeNode node = new TreeNodeEx("文档") { El = webBrowser1.Document.Body };
            webBrowser1.Document.Body.Style = "";
            webBrowser1.Document.Body.Click -= new HtmlElementEventHandler(Body_Click);
            webBrowser1.Document.Body.Click += new HtmlElementEventHandler(Body_Click);

            //treeView1.Nodes.Add(node);
            //NodeDictionary.Add(webBrowser1.Document.Body, new NodeEntity() { HElemrnt = webBrowser1.Document.Body, Node = node, Path = "0(body)" });
            //创建文档树
            //CreateTreeNode(webBrowser1.Document.Body, node);
            //添加文档事件
            //webBrowser1.Document.Body.MouseUp += new HtmlElementEventHandler(Body_MouseUp);
            webBrowser1.Document.Window.Error += new HtmlElementErrorEventHandler(Window_Error);
            //加载 Jquery 脚本
            //LoadScript();

        }

        //错误处理
        void Window_Error(object sender, HtmlElementErrorEventArgs e)
        {
            e.Handled = true;
        }

        /// <summary>
        /// 单击事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void Body_Click(object sender, HtmlElementEventArgs e)
        {
            var el = ((System.Windows.Forms.HtmlElement)(sender));

            el.Document.Body.Equals(webBrowser1.Document.Body);
            ///如果已经包含预览几直接返回
            if (el.Document.Body.OuterHtml.Contains("CollBrowserCE9D275C-13D8-4486-AFAD-F4AA151BA93D"))
            {
                return;
            }

            var path = webBrowser1.Document.InvokeScript("getCurrentPath");

            if (path != null)
            {
                List<PathItem> items = Newtonsoft.Json.JsonConvert.DeserializeObject<List<PathItem>>(path.ToString());
                HtmlElement db = null;
                try
                {
                    db = new ElementSearch(items).Find(webBrowser1.Document);
                }
                catch (NullReferenceException)
                {
                    DevComponents.DotNetBar.MessageBoxEx.Show("不能将指定区域转换成路径,请重新选择");
                    return;
                }
                //找到当前点击的原素

                if (db != null)
                {
                    #region 对不同的内容项进行填充
                    switch (State)
                    {
                        case 当前操作功能项状态.选取目录列表:
                            record.目录区域路径 = items;
                            break;
                        case 当前操作功能项状态.选取详细内容:
                            record.内容区域路径 = items;
                            break;
                        case 当前操作功能项状态.正在提取:
                            break;
                        case 当前操作功能项状态.选取分页区域:
                            record.分页区域路径 = items;
                            break;
                        case 当前操作功能项状态.提取分页索引:

                            break;
                        case 当前操作功能项状态.提取分页内容页面:

                            break;
                        case 当前操作功能项状态.分页页面内容页区域:
                            record.分页页面内容页区域 = items;
                            break;

                    }
                    #endregion

                    // MessageBox.Show(db.OuterHtml);
                }

            }
        }

        #region 没有什么作用的代码
        /// <summary>
        /// mouser 弹起时发生
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void Body_MouseUp(object sender, HtmlElementEventArgs e)
        {





            //new System.Threading.Thread(new System.Threading.ThreadStart(() =>
            //{

            //    System.Threading.Thread.Sleep(50);
            //    TagIndex = 0;

            //})).Start();


        }

        /// <summary>
        /// 创建文档树
        /// </summary>
        /// <param name="el"></param>
        /// <param name="node"></param>
        void CreateTreeNode(HtmlElement el, TreeNode node)
        {
            int n = 0;

            ///对子原素进行处理
            foreach (HtmlElement chel in el.Children)
            {
                var tempnode = new TreeNodeEx(chel.TagName) { El = chel };
                node.Nodes.Add(tempnode);
                NodeDictionary.Add(chel, new NodeEntity() { HElemrnt = chel, Node = tempnode, Path = NodeDictionary[el].Path + "," + n + "(" + chel.TagName + ")" });
                //子原素
                CreateTreeNode(chel, tempnode);
                n++;
                chel.Style = "";
                chel.Click += new HtmlElementEventHandler(el_Click);

            }
        }

        /// <summary>
        /// 单击事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void el_Click(object sender, HtmlElementEventArgs e)
        {
            if (TagIndex == 0)
            {
                foreach (var item in NodeDictionary.Values.ToArray())
                {
                    try
                    {
                        //移除所有的 样式事件
                        item.HElemrnt.Style = "";
                    }
                    catch { }
                }

                ((HtmlElement)sender).Style = "border: 2px dotted #00FF00;cursor:pointer;";
            }
            TagIndex++;
        }

        /// <summary>
        /// 选中后发生的事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
        {
            foreach (var item in NodeDictionary)
            {

                //移除所有的 样式事件
                item.Key.Style = "";
            }

            ((TreeNodeEx)treeView1.SelectedNode).El.Style = "border: 2px dotted #00FF00;cursor:pointer;";

        }
        #endregion






        /// <summary>
        /// 开始导航
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button1_Click(object sender, EventArgs e)
        {
            string url = comboBox1.Text as string;
            webBrowser1.Navigate(url);
            buttonSelect.Enabled = false;
            dataGridViewX1.Visible = false;
            #region 对不同的内容项进行填充
            switch (State)
            {
                case 当前操作功能项状态.选取目录列表:
                    record.基目录地址 = url;
                    break;
                case 当前操作功能项状态.选取详细内容:
                    record.基内容地址 = url;
                    break;
                case 当前操作功能项状态.正在提取:
                    break;
            }
            #endregion
        }


        /// <summary>
        /// 加载脚本
        /// </summary>
        protected void LoadScript()
        {
            if (webBrowser1.DocumentText != "")
            {
                webBrowser1.Document.Body.InnerHtml += "<style type='text/css'>.jqSelectedEl{border: 5px dotted #ff0000;cursor:pointer;}.jqSelectedhover{border: 2px dotted #00FF00;cursor:pointer;}</style>";

                webBrowser1.Document.InvokeScript("eval", new object[]{ 
            System.IO.File.ReadAllText(AppDomain.CurrentDomain.BaseDirectory + "jQuery1.4.1.js",Encoding.UTF8)
            });

                webBrowser1.Document.InvokeScript("eval", new object[]{ 
            System.IO.File.ReadAllText(AppDomain.CurrentDomain.BaseDirectory + "AppendScript.js",Encoding.UTF8)
            });
            }
        }

        /// <summary>
        /// 扩大选区
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        internal void buttonX2_Click(object sender, EventArgs e)
        {

            if (webBrowser1.Document.Body == null)
            {
                return;
            }

            ///如果已经包含预览几直接返回
            if (webBrowser1.Document.Body.OuterHtml.Contains("CollBrowserCE9D275C-13D8-4486-AFAD-F4AA151BA93D"))
            {
                return;
            }


            var path = webBrowser1.Document.InvokeScript("PervSelectSpace");

            if (path != null)
            {
                List<PathItem> items = Newtonsoft.Json.JsonConvert.DeserializeObject<List<PathItem>>(path.ToString());

                //找到当前点击的原素
                var db = new ElementSearch(items).Find(webBrowser1.Document);
                if (db != null)
                {
                    #region 对不同的内容项进行填充
                    switch (State)
                    {
                        case 当前操作功能项状态.选取目录列表:
                            record.目录区域路径 = items;
                            break;
                        case 当前操作功能项状态.选取详细内容:
                            record.内容区域路径 = items;
                            break;
                        case 当前操作功能项状态.正在提取:
                            break;
                        case 当前操作功能项状态.选取分页区域:
                            record.分页区域路径 = items;
                            break;
                        case 当前操作功能项状态.提取分页索引:

                            break;
                        case 当前操作功能项状态.提取分页内容页面:

                            break;
                        case 当前操作功能项状态.分页页面内容页区域:
                            record.分页页面内容页区域 = items;
                            break;

                    }
                    #endregion

                    // MessageBox.Show(db.OuterHtml);
                }

            }
        }

        /// <summary>
        /// 手动加载脚本
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        internal void buttonSelect_Click(object sender, EventArgs e)
        {
            LoadScript();
        }

        /// <summary>
        /// 切换总功能项 目录选取
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void buttonX目录_Click(object sender, EventArgs e)
        {
            State = 当前操作功能项状态.选取目录列表;
            Text = "当前功能:" + State;
            buttonX5.Enabled = false;
        }

        /// <summary>
        /// 切换总功能项为 详细
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void buttonX详细_Click(object sender, EventArgs e)
        {
            State = 当前操作功能项状态.选取详细内容;
            Text = "当前功能:" + State;
            comboBox1.Items.Clear();
            record.内容列表.Select(p => new { a = new Func<int>(() => { comboBox1.Items.Add(p.AbsoluteUri); return 0; }).Invoke() }).ToArray();
            buttonX5.Enabled = true;
        }

        /// <summary>
        /// 提取内容与目录 如果当前是目录的话就要提取出所有的url
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void buttonX4_Click(object sender, EventArgs e)
        {


            WebBrowser wb = (webBrowser1 as WebBrowser);

            ///如果已经包含预览几直接返回
            if (webBrowser1.Document.Body.OuterHtml.Contains("CollBrowserCE9D275C-13D8-4486-AFAD-F4AA151BA93D"))
            {
                return;
            }

            ///当前选择的区域原素
            HtmlElement currentEl = null;
            if (State == 当前操作功能项状态.选取目录列表)
            {
                currentEl = new ElementSearch(record.目录区域路径).Find(webBrowser1.Document);
            }
            if (State == 当前操作功能项状态.选取详细内容)
            {
                currentEl = new ElementSearch(record.内容区域路径).Find(webBrowser1.Document);
            }
            if (currentEl == null)
            {
                DevComponents.DotNetBar.MessageBoxEx.Show("不能将指定区域转换成路径,请重新选择");
                return;
            }


            //得到所页面中所有的A标题原素
            var allAElements = (from a in currentEl.GetElementsByTagName("a").Cast<HtmlElement>()
                                let href = ((mshtml.HTMLAnchorElement)(a.DomElement)).href
                                where href != null
                                select new Uri(href));
            //排序
            allAElements = allAElements.OrderBy(p => p.OriginalString);

            //对联接的路径深度进行排序
            allAElements = allAElements.OrderBy(p => p.Segments.Length);



            #region 对不同的内容项进行填充
            switch (State)
            {
                case 当前操作功能项状态.选取目录列表:
                    record.内容列表 = allAElements.ToList();
                    webBrowser1.Document.Body.InnerHtml = "<h1 id='CollBrowserCE9D275C-13D8-4486-AFAD-F4AA151BA93D'>[预览效果]</h1>" + currentEl.InnerHtml;
                    webBrowser1.Document.Body.Click -= new HtmlElementEventHandler(Body_Click);

                    break;
                case 当前操作功能项状态.选取详细内容:
                    webBrowser1.Document.Body.InnerHtml = "<h1 id='CollBrowserCE9D275C-13D8-4486-AFAD-F4AA151BA93D'>[预览效果]</h1>" + currentEl.InnerHtml;
                    webBrowser1.Document.Body.Click -= new HtmlElementEventHandler(Body_Click);
                    break;
                case 当前操作功能项状态.正在提取:
                    break;
                case 当前操作功能项状态.选取分页区域:
                    record.索引列表 = allAElements.ToList();
                    webBrowser1.Document.Body.InnerHtml = "<h1 id='CollBrowserCE9D275C-13D8-4486-AFAD-F4AA151BA93D'>[预览效果]</h1>" + currentEl.InnerHtml;
                    webBrowser1.Document.Body.Click -= new HtmlElementEventHandler(Body_Click);
                    break;
                case 当前操作功能项状态.提取分页索引:
                    break;
                case 当前操作功能项状态.提取分页内容页面:

                    break;

            }
            #endregion


        }

        /// <summary>
        /// 开始采集
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void buttonX5_Click(object sender, EventArgs e)
        {
            buttonX5.Enabled = false;
            dataGridViewX1.Visible = true;
            buttonX6.Enabled = true;
            timer.Interval = 200;
            workIndex = 0;
            progressBarX1.Value = 0;
            var source = (from p in record.内容列表
                          select new CollectionState()
                          {
                              目标地址 = p.AbsoluteUri,
                              当前状态 = "准备中..",
                              结果 = "",
                          }).Where(p => p.Browser != null).ToList();



            dataGridViewX1.DataSource = source;

            timer.Start();


        }
        /// <summary>
        /// 定时器 每次调用采集30条记录
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void timer_Tick(object sender, EventArgs e)
        {
            var source = (dataGridViewX1.DataSource as System.Collections.Generic.List<CollectionState>);
            if (source.Count == 0)
            {
                timer.Stop();
                return;
            }

            var currItem = source[workIndex];

            if (currItem.目标地址.Contains("mailto:") || !currItem.目标地址.Contains("http"))
            {

                currItem.当前状态 = "无法导航";
                workIndex++;
                return;
            }
            currItem.当前状态 = "正在处理..";
            currItem.Browser.Navigate(currItem.目标地址);
            currItem.Loading = true;
            currItem.Browser.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(webBrowser12_DocumentCompleted);
            workIndex++;
            progressBarX1.Value = workIndex * 100 / source.Count;
            if (source.Count == workIndex)
            {
                timer.Stop();
                buttonX5.Enabled = true;
                buttonX6.Enabled = false;
            }
            dataGridViewX1.Refresh();

        }


        /// <summary>
        /// 加载祥细完成后的事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void webBrowser12_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
        {
            WebBrowser wb = (sender as WebBrowser);
            //得到所有正在处理的记录
            var RunItems = (dataGridViewX1.DataSource as List<CollectionState>).Where(p => p.当前状态 == "正在处理..");


            //如果没有找到本地
            if (wb.IsOffline)
            {
                wb.Dispose();
                //返回出错
                return;
            }
            wb.DocumentCompleted -= new WebBrowserDocumentCompletedEventHandler(webBrowser12_DocumentCompleted);

            var current = (dataGridViewX1.DataSource as List<CollectionState>).Where(p => p.目标地址 == e.Url.AbsoluteUri);


            ///如果已经包含预览几直接返回
            if (wb.Document.Body.OuterHtml.Contains("CollBrowserCE9D275C-13D8-4486-AFAD-F4AA151BA93D"))
            {
                return;
            }

            ///当前选择的区域原素
            HtmlElement currentEl = null;
            try
            {
                currentEl = new ElementSearch(record.内容区域路径).Find(wb.Document);
            }
            catch
            {
                if (current.Count() > 0)
                {
                    current.First().当前状态 = "出错..";
                    current.First().Loading = false;
                }

                return;
            }
            if (currentEl == null)
            {
                return;
            }


            if ((dataGridViewX1.DataSource as List<CollectionState>) != null)
            {
                if (current.Count() > 0)
                {
                    current.First().结果 = currentEl.InnerText;
                    current.First().当前状态 = "完成";
                    current.First().Loading = false;

                }
            }

            wb.Dispose();


        }

        /// <summary>
        /// 暂停,继续
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void buttonX6_Click(object sender, EventArgs e)
        {
            if (pause)
            {
                buttonX6.Text = "暂停";
                pause = false;
                timer.Start();
            }
            else
            {
                buttonX6.Text = "继续";
                pause = true;
                timer.Stop();

            }
        }

        /// <summary>
        ///选取分页区域
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void buttonX7_Click(object sender, EventArgs e)
        {
            State = 当前操作功能项状态.选取分页区域;

            new SplitPages() { ParentForm = this, Wb = webBrowser1 }.Show();
        }
        /// <summary>
        /// 选取页面标题
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void buttonX8_Click(object sender, EventArgs e)
        {

        }





    }
}
